<div class="tmd-doc">
<h1 class="tmd-header-1">
<code class="tmd-code-span">nil</code>s in Go
</h1>
<p></p>
<div class="tmd-usual">
<code class="tmd-code-span">nil</code> is a frequently used and important predeclared identifier in Go. It is the literal representation of zero values of many kinds of types. Many new Go programmers with experiences of some other popular languages may view <code class="tmd-code-span">nil</code> as the counterpart of <code class="tmd-code-span">null</code> (or <code class="tmd-code-span">NULL</code>) in other languages. This is partly right, but there are many differences between <code class="tmd-code-span">nil</code> in Go and <code class="tmd-code-span">null</code> (or <code class="tmd-code-span">NULL</code>) in other languages.
</div>
<p></p>
<div class="tmd-usual">
The remaining of this article will list all kinds of facts and details related to <code class="tmd-code-span">nil</code>.
</div>
<p></p>
<h3 class="tmd-header-3">
<code class="tmd-code-span">nil</code> Is a Predeclared Identifier in Go
</h3>
<p></p>
<div class="tmd-usual">
We can use <code class="tmd-code-span">nil</code> without declaring it.
</div>
<p></p>
<h3 class="tmd-header-3">
<code class="tmd-code-span">nil</code> Can Represent Zero Values of Many Types
</h3>
<p></p>
<div class="tmd-usual">
In Go, <code class="tmd-code-span">nil</code> can represent zero values of the following kinds of types:
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
pointer types (including type-unsafe ones).
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
map types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
slice types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
function types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
channel types.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
interface types.
</div>
</li>
</ul>
<p></p>
<h3 class="tmd-header-3">
Predeclared <code class="tmd-code-span">nil</code> Has Not a Default Type
</h3>
<p></p>
<div class="tmd-usual">
Each of other predeclared identifiers in Go has a default type. For example,
</div>
<ul class="tmd-list">
<li class="tmd-list-item">
<div class="tmd-usual">
the default types of <code class="tmd-code-span">true</code> and <code class="tmd-code-span">false</code> are both <code class="tmd-code-span">bool</code> type.
</div>
</li>
<li class="tmd-list-item">
<div class="tmd-usual">
the default type of <code class="tmd-code-span">iota</code> is <code class="tmd-code-span">int</code>.
</div>
</li>
</ul>
<p></p>
<div class="tmd-usual">
But the predeclared <code class="tmd-code-span">nil</code> has not a default type, though it has many possible types. In fact, the predeclared <code class="tmd-code-span">nil</code> is the only untyped value who has not a default type in Go. There must be sufficient information for compiler to deduce the type of a <code class="tmd-code-span">nil</code> from context.
</div>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

func main() {
	// There must be sufficient information for
	// compiler to deduce the type of a nil value.
	_ = (*struct{})(nil)
	_ = []int(nil)
	_ = map[int]bool(nil)
	_ = chan string(nil)
	_ = (func())(nil)
	_ = interface{}(nil)

	// These lines are equivalent to the above lines.
	var _ *struct{} = nil
	var _ []int = nil
	var _ map[int]bool = nil
	var _ chan string = nil
	var _ func() = nil
	var _ interface{} = nil

	// This following line doesn't compile.
	var _ = nil
}
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Predeclared <code class="tmd-code-span">nil</code> Is Not a Keyword in Go
</h3>
<p></p>
<div class="tmd-usual">
The predeclared <code class="tmd-code-span">nil</code> can be shadowed.
</div>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import "fmt"

func main() {
	nil := 123
	fmt.Println(nil) // 123

	// The following line fails to compile,
	// for nil represents an int value now
	// in this scope.
	var _ map[string]int = nil
}
</code></pre>
<p></p>
<div class="tmd-usual">
<span class="tmd-italic">(BTW, <code class="tmd-code-span">null</code> and <code class="tmd-code-span">NULL</code> in many other languages are also not keywords.)</span>
</div>
<p></p>
<h3 id="sizes" class="tmd-header-3">
The Sizes of Nil Values With Types of Different Kinds May Be Different
</h3>
<p></p>
<div class="tmd-usual">
The memory layouts of all values of a type are always the same. nil values of the type are not exceptions (assume the zero values of the type can be represented as <code class="tmd-code-span">nil</code>). The size of a nil value is always the same as the sizes of non-nil values whose types are the same as the nil value. But nil values of different kinds of types may have different sizes.
</div>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var p *struct{} = nil
	fmt.Println( unsafe.Sizeof( p ) ) // 8

	var s []int = nil
	fmt.Println( unsafe.Sizeof( s ) ) // 24

	var m map[int]bool = nil
	fmt.Println( unsafe.Sizeof( m ) ) // 8

	var c chan string = nil
	fmt.Println( unsafe.Sizeof( c ) ) // 8

	var f func() = nil
	fmt.Println( unsafe.Sizeof( f ) ) // 8

	var i interface{} = nil
	fmt.Println( unsafe.Sizeof( i ) ) // 16
}
</code></pre>
<p></p>
<div class="tmd-usual">
The sizes are compiler and architecture dependent. The above printed results are for 64-bit architectures and the standard Go compiler. For 32-bit architectures, the printed sizes will be half.
</div>
<p></p>
<div class="tmd-usual">
For the standard Go compiler, the sizes of two values of different types of the same kind whose zero values can be represented as the predeclared <code class="tmd-code-span">nil</code> are always the same. For example, the sizes of all values of all different slice types are the same.
</div>
<p></p>
<h3 class="tmd-header-3">
Two Nil Values of Two Different Types May Be Not Comparable
</h3>
<p></p>
<div class="tmd-usual">
For example, the two comparisons in the following example both fail to compile. The reason is, in each comparison, neither operand can be implicitly converted to the type of the other.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// Compilation failure reason: mismatched types.
var _ = (*int)(nil) == (*bool)(nil)         // error
var _ = (chan int)(nil) == (chan bool)(nil) // error
</code></pre>
<p></p>
<div class="tmd-usual">
Please read <a href="value-conversions-assignments-and-comparisons.html#comparison-rules">comparison rules in Go</a> to get which two values can be compared with each other. Typed <code class="tmd-code-span">nil</code> values are not exceptions of the comparison rules.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
The code lines in the following example all compile okay.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">type IntPtr *int
// The underlying of type IntPtr is *int.
var _ = IntPtr(nil) == (*int)(nil)

// Every type in Go implements interface{} type.
var _ = (interface{})(nil) == (*int)(nil)

// Values of a directional channel type can be
// converted to the bidirectional channel type
// which has the same element type.
var _ = (chan int)(nil) == (chan&lt;- int)(nil)
var _ = (chan int)(nil) == (&lt;-chan int)(nil)
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Two Nil Values of the Same Type May Be Not Comparable
</h3>
<p></p>
<div class="tmd-usual">
In Go, map, slice and function types don't support comparison. Comparing two values, including nil values, of an incomparable types is illegal. The following comparisons fail to compile.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">var _ = ([]int)(nil) == ([]int)(nil)
var _ = (map[string]int)(nil) == (map[string]int)(nil)
var _ = (func())(nil) == (func())(nil)
</code></pre>
<p></p>
<div class="tmd-usual">
But any values of the above mentioned incomparable types can be compared with the bare <code class="tmd-code-span">nil</code> identifier.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">// The following lines compile okay.
var _ = ([]int)(nil) == nil
var _ = (map[string]int)(nil) == nil
var _ = (func())(nil) == nil
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Two Nil Values May Be Not Equal
</h3>
<p></p>
<div class="tmd-usual">
If one of the two compared nil values is an interface value and the other is not, assume they are comparable, then the comparison result is always <code class="tmd-code-span">false</code>. The reason is the non-interface value will be <a href="interface.html#boxing">converted to the type of the interface value</a> before making the comparison. The converted interface value has a dynamic type but the other interface value has not. That is why the comparison result is always <code class="tmd-code-span">false</code>.
</div>
<p></p>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code disable-line-numbers111">
<code class="language-go">fmt.Println( (interface{})(nil) == (*int)(nil) ) // false
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Retrieving Elements From Nil Maps Will Not Panic
</h3>
<p></p>
<div class="tmd-usual">
Retrieving element from a nil map value will always return a zero element value.
</div>
<p></p>
<div class="tmd-usual">
For example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">fmt.Println( (map[string]int)(nil)["key"] ) // 0
fmt.Println( (map[int]bool)(nil)[123] )     // false
fmt.Println( (map[int]*int64)(nil)[123] )   // &lt;nil&gt;
</code></pre>
<p></p>
<h3 class="tmd-header-3">
It Is Legal to Range Over Nil Channels, Maps, Slices, and Array Pointers
</h3>
<p></p>
<div class="tmd-usual">
The number of loop steps by iterate nil maps and slices is zero.
</div>
<p></p>
<div class="tmd-usual">
The number of loop steps by iterate a nil array pointer is the length of its corresponding array type. (However, if the length of the corresponding array type is not zero, and the second iteration is neither ignored nor omitted, the iteration will panic at run time.)
</div>
<p></p>
<div class="tmd-usual">
Ranging over a nil channel will block the current goroutine for ever.
</div>
<p></p>
<div class="tmd-usual">
For example, the following code will print <code class="tmd-code-span">0</code>, <code class="tmd-code-span">1</code>, <code class="tmd-code-span">2</code>, <code class="tmd-code-span">3</code> and <code class="tmd-code-span">4</code>, then block for ever. <code class="tmd-code-span">Hello</code>, <code class="tmd-code-span">world</code> and <code class="tmd-code-span">Bye</code> will never be printed.
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">for range []int(nil) {
	fmt.Println("Hello")
}

for range map[string]string(nil) {
	fmt.Println("world")
}

for i := range (*[5]int)(nil) {
	fmt.Println(i)
}

for range chan bool(nil) { // block here
	fmt.Println("Bye")
}
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Invoking Methods Through Non-Interface Nil Receiver Arguments Will Not Panic
</h3>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

type Slice []bool

func (s Slice) Length() int {
	return len(s)
}

func (s Slice) Modify(i int, x bool) {
	s[i] = x // panic if s is nil
}

func (p *Slice) DoNothing() {
}

func (p *Slice) Append(x bool) {
	*p = append(*p, x) // panic if p is nil
}

func main() {
	// The following selectors will not cause panics.
	_ = ((Slice)(nil)).Length
	_ = ((Slice)(nil)).Modify
	_ = ((*Slice)(nil)).DoNothing
	_ = ((*Slice)(nil)).Append

	// The following two lines will also not panic.
	_ = ((Slice)(nil)).Length()
	((*Slice)(nil)).DoNothing()

	// The following two lines will panic. But panics
	// will not be triggered at the time of invoking
	// the methods. They will be triggered on
	// dereferencing nil pointers in the method bodies.
	/*
	((Slice)(nil)).Modify(0, true)
	((*Slice)(nil)).Append(true)
	*/
}
</code></pre>
<p></p>
<div class="tmd-usual">
In fact, the above implementation of the <code class="tmd-code-span">Append</code> method is not perfect, it should be modified as the following one.
</div>
<p></p>
<pre class="tmd-code line-numbers">
<code class="language-go">func (p *Slice) Append(x bool) {
	if p == nil {
		*p = []bool{x}
		return
	}
	*p = append(*p, x)
}
</code></pre>
<p></p>
<h3 class="tmd-header-3">
<code class="tmd-code-span">*new(T)</code> Results a Nil <code class="tmd-code-span">T</code> Value if the Zero Value of Type <code class="tmd-code-span">T</code> Is Represented With the Predeclared <code class="tmd-code-span">nil</code> Identifier
</h3>
<p></p>
<div class="tmd-usual">
Example:
</div>
<pre class="tmd-code line-numbers">
<code class="language-go">package main

import "fmt"

func main() {
	fmt.Println(*new(*int) == nil)         // true
	fmt.Println(*new([]int) == nil)        // true
	fmt.Println(*new(map[int]bool) == nil) // true
	fmt.Println(*new(chan string) == nil)  // true
	fmt.Println(*new(func()) == nil)       // true
	fmt.Println(*new(interface{}) == nil)  // true
}
</code></pre>
<p></p>
<h3 class="tmd-header-3">
Summary
</h3>
<p></p>
<div class="tmd-usual">
In Go, for simplicity and convenience, <code class="tmd-code-span">nil</code> is designed as an identifier which can be used to represent the zero values of some kinds of types. It is not a single value. It can represent many values with different memory layouts.
</div>
</div>
